package utils

import (
	"context"
	jwt "github.com/gogf/gf-jwt/v2"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/util/gconv"
	"miaoyu/internal/model"
	"miaoyu/internal/service"
	"miaoyu/internal/utility"
	"time"
)

type sActAuth struct {
	jwtMid *jwt.GfJWTMiddleware
}

func init() {
	service.RegisterActAuth(NewActAuth())
}

func NewActAuth() *sActAuth {
	sAuth := sActAuth{}
	jwtMid := jwt.New(&jwt.GfJWTMiddleware{
		Realm:         "miaoyu wechat",
		Key:           []byte("miaoyu wechat key"),
		Timeout:       time.Minute * 120,
		MaxRefresh:    time.Hour * 24,
		IdentityKey:   "info",
		TokenLookup:   "header:Authorization,query:token,cookie:jwt",
		TokenHeadName: "mytoken",
		TimeFunc:      time.Now,
		//Authenticator:   Authenticator,
		Unauthorized:    sAuth.Unauthorized,
		PayloadFunc:     sAuth.PayLoadFunc,
		IdentityHandler: sAuth.IdentityHandler,
	})
	sAuth.jwtMid = jwtMid
	return &sAuth
}

func (s *sActAuth) MiddlewareFunc() ghttp.HandlerFunc {
	return s.jwtMid.MiddlewareFunc()
}

func (s *sActAuth) GetIdentity(ctx context.Context) uint {

	return gconv.Uint(s.jwtMid.GetIdentity(ctx))
}

// PayLoadFunc 登录期间的设置私有载荷的函数，默认设置authenticator函数回调的所有内容
func (s *sActAuth) PayLoadFunc(data interface{}) jwt.MapClaims {
	claims := jwt.MapClaims{}
	params := data.(map[string]interface{})
	if len(params) > 0 {
		for k, v := range params {
			claims[k] = v
		}
	}
	return claims
}

// IdentityHandler 登录验证完成 ，解析并设置用户身份信息，并设置身份信息至每次请求中
func (s *sActAuth) IdentityHandler(ctx context.Context) interface{} {
	claims := jwt.ExtractClaims(ctx)
	//fmt.Println("验证用户成功信息部分", claims)
	desStr, err := utility.AesDecrypt(gconv.String(claims[s.jwtMid.IdentityKey]))
	if err != nil {
		g.Log().Error(ctx, "act解析失败", err)
		return 0
	}
	//验证完用户 储存用户信息

	return desStr
}

// Unauthorized 登录验证失败，处理不进行授权的逻辑
func (s *sActAuth) Unauthorized(ctx context.Context, code int, message string) {
	r := g.RequestFromCtx(ctx)
	//fmt.Println("验证用户未登录授权情况")
	//curPath := r.Request.URL.Path
	//访问路由匹配
	curRouter := r.Router.Uri
	//fmt.Println("路由", curRouter)
	// r.Router.uri 系统的注册路由，元数据可以直接匹配
	checkRes := utility.CheckRouteAuth(curRouter)
	//fmt.Println("路由验证结果:", checkRes)
	service.ActSession().RemoveUser(ctx)
	if checkRes {
		r.Middleware.Next()
	} else {
		//, utility.GetRouteByKey("activity/votes/vote/index"))
		service.JsonResp().CommonResp(r).SetErrorJsonExit("请到“山东省交通运输厅”微信公众号上进行推选！")
	}

}
func (s *sActAuth) GetPayload(ctx context.Context) string {
	return s.jwtMid.GetPayload(ctx)
}
func (s *sActAuth) TokenGenerator(data model.ContextUser) (jwt model.JWTInfo, err error) {

	genData := make(map[string]interface{})
	aesStr, aesErr := utility.AesEncrypt(gconv.String(data.Id))
	if aesErr != nil {
		err = aesErr
		return
	}
	genData["info"] = aesStr
	genData["username"] = data.UserName

	token, expire, resErr := s.jwtMid.TokenGenerator(genData)
	if resErr != nil {
		err = resErr
		return jwt, err
	}
	jwt.Token = token
	jwt.Expire = expire

	return
}
func (s *sActAuth) RefreshHandler(ctx context.Context) (token string, expire time.Time) {
	token, expire = s.jwtMid.RefreshHandler(ctx)
	return
}
func (s *sActAuth) LogoutHandler(ctx context.Context) {
	s.jwtMid.LogoutHandler(ctx)
	return
}
